// Copyright 2017-present the Material Components for iOS authors. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#import <XCTest/XCTest.h>

#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wprivate-header"
#import "MDCAppBarButtonBarBuilder.h"
#pragma clang diagnostic pop
#import "MDCButtonBar.h"
#import "MDCButton.h"
#import "MDCInkView.h"

NS_ASSUME_NONNULL_BEGIN

@interface MDCAppBarButtonBarBuilder (UnitTests)
+ (void)configureButton:(MDCButton *)destinationButton
         fromButtonItem:(nullable UIBarButtonItem *)sourceButtonItem;

+ (UIEdgeInsets)contentInsetsForButton:(MDCButton *)button
                        layoutPosition:(MDCButtonBarLayoutPosition)layoutPosition
                           layoutHints:(MDCBarButtonItemLayoutHints)layoutHints
                       layoutDirection:(UIUserInterfaceLayoutDirection)layoutDirection
                    userInterfaceIdiom:(UIUserInterfaceIdiom)userInterfaceIdiom;
@end

@interface ButtonBarBuilderTests : XCTestCase

@end

@implementation ButtonBarBuilderTests

#pragma mark - +contentInsetsForButton:layoutPosition:layoutHints:layoutDirection:userInterfaceIdiom:
- (void)testContentInsetsEqualForInterfaceLayoutIdiomPhone {
  // Given
  MDCButton *imageButton = [[MDCButton alloc] initWithFrame:CGRectZero];
  [imageButton setImage:[[UIImage alloc] init] forState:UIControlStateNormal];

  // When
  UIEdgeInsets ltrImageInsetsFirst =
      [MDCAppBarButtonBarBuilder contentInsetsForButton:imageButton
                                         layoutPosition:MDCButtonBarLayoutPositionLeading
                                            layoutHints:MDCBarButtonItemLayoutHintsIsFirstButton
                                        layoutDirection:UIUserInterfaceLayoutDirectionLeftToRight
                                     userInterfaceIdiom:UIUserInterfaceIdiomPhone];
  UIEdgeInsets rtlImageInsetsFirst =
      [MDCAppBarButtonBarBuilder contentInsetsForButton:imageButton
                                         layoutPosition:MDCButtonBarLayoutPositionLeading
                                            layoutHints:MDCBarButtonItemLayoutHintsIsFirstButton
                                        layoutDirection:UIUserInterfaceLayoutDirectionRightToLeft
                                     userInterfaceIdiom:UIUserInterfaceIdiomPhone];
  UIEdgeInsets ltrImageInsetsLast =
      [MDCAppBarButtonBarBuilder contentInsetsForButton:imageButton
                                         layoutPosition:MDCButtonBarLayoutPositionLeading
                                            layoutHints:MDCBarButtonItemLayoutHintsIsLastButton
                                        layoutDirection:UIUserInterfaceLayoutDirectionLeftToRight
                                     userInterfaceIdiom:UIUserInterfaceIdiomPhone];
  UIEdgeInsets rtlImageInsetsLast =
      [MDCAppBarButtonBarBuilder contentInsetsForButton:imageButton
                                         layoutPosition:MDCButtonBarLayoutPositionLeading
                                            layoutHints:MDCBarButtonItemLayoutHintsIsLastButton
                                        layoutDirection:UIUserInterfaceLayoutDirectionRightToLeft
                                     userInterfaceIdiom:UIUserInterfaceIdiomPhone];

  // Then
  XCTAssertEqual(ltrImageInsetsFirst.left, rtlImageInsetsFirst.right);
  XCTAssertEqual(ltrImageInsetsFirst.right, rtlImageInsetsFirst.left);
  XCTAssertEqual(ltrImageInsetsFirst.top, rtlImageInsetsFirst.top);
  XCTAssertEqual(ltrImageInsetsFirst.bottom, rtlImageInsetsFirst.bottom);

  XCTAssertEqual(ltrImageInsetsLast.left, rtlImageInsetsLast.right);
  XCTAssertEqual(ltrImageInsetsLast.right, rtlImageInsetsLast.left);
  XCTAssertEqual(ltrImageInsetsLast.top, rtlImageInsetsLast.top);
  XCTAssertEqual(ltrImageInsetsLast.bottom, rtlImageInsetsLast.bottom);
}

- (void)testContentInsetsEqualForInterfaceLayoutIdiomPad {
  // Given
  MDCButton *imageButton = [[MDCButton alloc] initWithFrame:CGRectZero];
  [imageButton setImage:[[UIImage alloc] init] forState:UIControlStateNormal];

  // When
  UIEdgeInsets ltrImageInsetsFirst =
      [MDCAppBarButtonBarBuilder contentInsetsForButton:imageButton
                                         layoutPosition:MDCButtonBarLayoutPositionLeading
                                            layoutHints:MDCBarButtonItemLayoutHintsIsFirstButton
                                        layoutDirection:UIUserInterfaceLayoutDirectionLeftToRight
                                     userInterfaceIdiom:UIUserInterfaceIdiomPad];
  UIEdgeInsets rtlImageInsetsFirst =
      [MDCAppBarButtonBarBuilder contentInsetsForButton:imageButton
                                         layoutPosition:MDCButtonBarLayoutPositionLeading
                                            layoutHints:MDCBarButtonItemLayoutHintsIsFirstButton
                                        layoutDirection:UIUserInterfaceLayoutDirectionRightToLeft
                                     userInterfaceIdiom:UIUserInterfaceIdiomPad];
  UIEdgeInsets ltrImageInsetsLast =
      [MDCAppBarButtonBarBuilder contentInsetsForButton:imageButton
                                         layoutPosition:MDCButtonBarLayoutPositionLeading
                                            layoutHints:MDCBarButtonItemLayoutHintsIsLastButton
                                        layoutDirection:UIUserInterfaceLayoutDirectionLeftToRight
                                     userInterfaceIdiom:UIUserInterfaceIdiomPad];
  UIEdgeInsets rtlImageInsetsLast =
      [MDCAppBarButtonBarBuilder contentInsetsForButton:imageButton
                                         layoutPosition:MDCButtonBarLayoutPositionLeading
                                            layoutHints:MDCBarButtonItemLayoutHintsIsLastButton
                                        layoutDirection:UIUserInterfaceLayoutDirectionRightToLeft
                                     userInterfaceIdiom:UIUserInterfaceIdiomPad];

  // Then
  XCTAssertEqual(ltrImageInsetsFirst.left, rtlImageInsetsFirst.right);
  XCTAssertEqual(ltrImageInsetsFirst.right, rtlImageInsetsFirst.left);
  XCTAssertEqual(ltrImageInsetsFirst.top, rtlImageInsetsFirst.top);
  XCTAssertEqual(ltrImageInsetsFirst.bottom, rtlImageInsetsFirst.bottom);

  XCTAssertEqual(ltrImageInsetsLast.left, rtlImageInsetsLast.right);
  XCTAssertEqual(ltrImageInsetsLast.right, rtlImageInsetsLast.left);
  XCTAssertEqual(ltrImageInsetsLast.top, rtlImageInsetsLast.top);
  XCTAssertEqual(ltrImageInsetsLast.bottom, rtlImageInsetsLast.bottom);
}

- (void)testContentInsetsMirroredForTrailing {
  // Given
  MDCButton *imageButton = [[MDCButton alloc] initWithFrame:CGRectZero];
  [imageButton setImage:[[UIImage alloc] init] forState:UIControlStateNormal];

  // When
  UIEdgeInsets insetsFirstLeading =
      [MDCAppBarButtonBarBuilder contentInsetsForButton:imageButton
                                         layoutPosition:MDCButtonBarLayoutPositionLeading
                                            layoutHints:MDCBarButtonItemLayoutHintsIsFirstButton
                                        layoutDirection:UIUserInterfaceLayoutDirectionLeftToRight
                                     userInterfaceIdiom:UIUserInterfaceIdiomPhone];
  UIEdgeInsets insetsFirstTrailing =
      [MDCAppBarButtonBarBuilder contentInsetsForButton:imageButton
                                         layoutPosition:MDCButtonBarLayoutPositionTrailing
                                            layoutHints:MDCBarButtonItemLayoutHintsIsFirstButton
                                        layoutDirection:UIUserInterfaceLayoutDirectionLeftToRight
                                     userInterfaceIdiom:UIUserInterfaceIdiomPhone];

  UIEdgeInsets insetsLastLeading =
      [MDCAppBarButtonBarBuilder contentInsetsForButton:imageButton
                                         layoutPosition:MDCButtonBarLayoutPositionLeading
                                            layoutHints:MDCBarButtonItemLayoutHintsIsLastButton
                                        layoutDirection:UIUserInterfaceLayoutDirectionLeftToRight
                                     userInterfaceIdiom:UIUserInterfaceIdiomPhone];
  UIEdgeInsets insetsLastTrailing =
      [MDCAppBarButtonBarBuilder contentInsetsForButton:imageButton
                                         layoutPosition:MDCButtonBarLayoutPositionTrailing
                                            layoutHints:MDCBarButtonItemLayoutHintsIsLastButton
                                        layoutDirection:UIUserInterfaceLayoutDirectionLeftToRight
                                     userInterfaceIdiom:UIUserInterfaceIdiomPhone];

  // Then
  XCTAssertEqual(insetsFirstLeading.left, insetsFirstTrailing.right);
  XCTAssertEqual(insetsLastLeading.right, insetsLastTrailing.left);
}

- (void)testContentInsetsEqualForTitleAndImageButtonIdiomPhone {
  // Given
  MDCButton *titleButton = [[MDCButton alloc] initWithFrame:CGRectZero];
  [titleButton setTitle:@"Title" forState:UIControlStateNormal];
  MDCButton *imageButton = [[MDCButton alloc] initWithFrame:CGRectZero];
  [imageButton setImage:[[UIImage alloc] init] forState:UIControlStateNormal];

  // When
  UIEdgeInsets imageInsetsFirst =
      [MDCAppBarButtonBarBuilder contentInsetsForButton:imageButton
                                         layoutPosition:MDCButtonBarLayoutPositionLeading
                                            layoutHints:MDCBarButtonItemLayoutHintsIsFirstButton
                                        layoutDirection:UIUserInterfaceLayoutDirectionLeftToRight
                                     userInterfaceIdiom:UIUserInterfaceIdiomPhone];
  UIEdgeInsets titleInsetsFirst =
      [MDCAppBarButtonBarBuilder contentInsetsForButton:titleButton
                                         layoutPosition:MDCButtonBarLayoutPositionLeading
                                            layoutHints:MDCBarButtonItemLayoutHintsIsFirstButton
                                        layoutDirection:UIUserInterfaceLayoutDirectionLeftToRight
                                     userInterfaceIdiom:UIUserInterfaceIdiomPhone];
  UIEdgeInsets imageInsetsLast =
      [MDCAppBarButtonBarBuilder contentInsetsForButton:imageButton
                                         layoutPosition:MDCButtonBarLayoutPositionLeading
                                            layoutHints:MDCBarButtonItemLayoutHintsIsLastButton
                                        layoutDirection:UIUserInterfaceLayoutDirectionLeftToRight
                                     userInterfaceIdiom:UIUserInterfaceIdiomPhone];
  UIEdgeInsets titleInsetsLast =
      [MDCAppBarButtonBarBuilder contentInsetsForButton:titleButton
                                         layoutPosition:MDCButtonBarLayoutPositionLeading
                                            layoutHints:MDCBarButtonItemLayoutHintsIsLastButton
                                        layoutDirection:UIUserInterfaceLayoutDirectionLeftToRight
                                     userInterfaceIdiom:UIUserInterfaceIdiomPhone];

  // Then
  XCTAssertEqual(imageInsetsFirst.left, titleInsetsFirst.left);
  XCTAssertEqual(imageInsetsFirst.right, titleInsetsFirst.right);
  XCTAssertEqual(imageInsetsLast.left, titleInsetsLast.left);
  XCTAssertEqual(imageInsetsLast.right, titleInsetsLast.right);
}

- (void)testContentInsetsEqualForTitleAndImageButtonIdiomPad {
  // Given
  MDCButton *titleButton = [[MDCButton alloc] initWithFrame:CGRectZero];
  [titleButton setTitle:@"Title" forState:UIControlStateNormal];
  MDCButton *imageButton = [[MDCButton alloc] initWithFrame:CGRectZero];
  [imageButton setImage:[[UIImage alloc] init] forState:UIControlStateNormal];

  // When
  UIEdgeInsets imageInsetsFirst =
      [MDCAppBarButtonBarBuilder contentInsetsForButton:imageButton
                                         layoutPosition:MDCButtonBarLayoutPositionLeading
                                            layoutHints:MDCBarButtonItemLayoutHintsIsFirstButton
                                        layoutDirection:UIUserInterfaceLayoutDirectionLeftToRight
                                     userInterfaceIdiom:UIUserInterfaceIdiomPad];
  UIEdgeInsets titleInsetsFirst =
      [MDCAppBarButtonBarBuilder contentInsetsForButton:titleButton
                                         layoutPosition:MDCButtonBarLayoutPositionLeading
                                            layoutHints:MDCBarButtonItemLayoutHintsIsFirstButton
                                        layoutDirection:UIUserInterfaceLayoutDirectionLeftToRight
                                     userInterfaceIdiom:UIUserInterfaceIdiomPad];
  UIEdgeInsets imageInsetsLast =
      [MDCAppBarButtonBarBuilder contentInsetsForButton:imageButton
                                         layoutPosition:MDCButtonBarLayoutPositionLeading
                                            layoutHints:MDCBarButtonItemLayoutHintsIsLastButton
                                        layoutDirection:UIUserInterfaceLayoutDirectionLeftToRight
                                     userInterfaceIdiom:UIUserInterfaceIdiomPad];
  UIEdgeInsets titleInsetsLast =
      [MDCAppBarButtonBarBuilder contentInsetsForButton:titleButton
                                         layoutPosition:MDCButtonBarLayoutPositionLeading
                                            layoutHints:MDCBarButtonItemLayoutHintsIsLastButton
                                        layoutDirection:UIUserInterfaceLayoutDirectionLeftToRight
                                     userInterfaceIdiom:UIUserInterfaceIdiomPad];

  // Then
  XCTAssertEqual(imageInsetsFirst.left, titleInsetsFirst.left);
  XCTAssertEqual(imageInsetsFirst.right, titleInsetsFirst.right);
  XCTAssertEqual(imageInsetsLast.left, titleInsetsLast.left);
  XCTAssertEqual(imageInsetsLast.right, titleInsetsLast.right);
}

#pragma mark - +configureButton:fromButtonItem:
- (void)testConfigureButtonFromNilItem {
  // Given
  MDCButton *destinationButton = [[MDCButton alloc] initWithFrame:CGRectZero];
  NSString *defaultTitle = [destinationButton titleForState:UIControlStateNormal];
  UIColor *defaultTintColor = destinationButton.tintColor;
  UIImage *defaultImage = [destinationButton imageForState:UIControlStateNormal];
  MDCInkStyle defaultInkStyle = destinationButton.inkStyle;
  NSInteger defaultTag = destinationButton.tag;

  // When
  [MDCAppBarButtonBarBuilder configureButton:destinationButton fromButtonItem:nil];

  // Then
  XCTAssertEqualObjects([destinationButton titleForState:UIControlStateNormal], defaultTitle);
  XCTAssertEqualObjects([destinationButton imageForState:UIControlStateNormal], defaultImage);
  XCTAssertEqualObjects(destinationButton.tintColor, defaultTintColor);
  XCTAssertEqual(destinationButton.inkStyle, defaultInkStyle);
  XCTAssertEqual(destinationButton.tag, defaultTag);
}

- (void)testConfigureButtonFromButtonItemWithTitle {
  // Given
  UIBarButtonItem *itemWithTitle = [[UIBarButtonItem alloc] initWithTitle:@"Title"
                                                                    style:UIBarButtonItemStylePlain
                                                                   target:nil
                                                                   action:nil];
  itemWithTitle.tag = 0x02468ace;
  itemWithTitle.tintColor = [UIColor colorWithRed:0.5 green:0.25 blue:0.75 alpha:0.125];
  MDCButton *destinationButton = [[MDCButton alloc] initWithFrame:CGRectZero];

  // When
  [MDCAppBarButtonBarBuilder configureButton:destinationButton fromButtonItem:itemWithTitle];

  // Then
  NSString *expectedTitle = destinationButton.isUppercaseTitle
                                ? [itemWithTitle.title uppercaseString]
                                : itemWithTitle.title;
  XCTAssertEqualObjects(
      [destinationButton titleForState:UIControlStateNormal], expectedTitle,
      @"The MDC button should have a normal state title equal to the UIBarButtonItem's title.");
  XCTAssertEqualObjects(destinationButton.tintColor, itemWithTitle.tintColor,
                        @"The MDC button should have the same tint as the UIBarButtonItem");
  XCTAssertNil([destinationButton imageForState:UIControlStateNormal],
               @"The MDC button should not receive a normal state image if the UIBarButtonItem did "
               @"not have one.");
  XCTAssertEqual(destinationButton.inkStyle, MDCInkStyleBounded,
                 @"MDC buttons with text should use bounded ink when used within a button bar.");
  XCTAssertEqual(destinationButton.tag, itemWithTitle.tag,
                 @"The MDC button should have the same tag as the UIBarButtonItem.");
}

- (void)testConfigureButtonFromButtonItemWithImage {
  // Given
  UIBarButtonItem *itemWithImage = [[UIBarButtonItem alloc] initWithImage:[[UIImage alloc] init]
                                                                    style:UIBarButtonItemStylePlain
                                                                   target:nil
                                                                   action:nil];
  itemWithImage.tag = 0x13579bdf;
  itemWithImage.tintColor = [UIColor colorWithRed:0.75 green:0.5 blue:0.125 alpha:0.25];
  MDCButton *destinationButton = [[MDCButton alloc] initWithFrame:CGRectZero];

  // When
  [MDCAppBarButtonBarBuilder configureButton:destinationButton fromButtonItem:itemWithImage];

  // Then
  XCTAssertNil(
      [destinationButton titleForState:UIControlStateNormal],
      @"The MDC button should have no title in the normal state if the UIBarButtonItem had none.");
  XCTAssertEqualObjects(destinationButton.tintColor, itemWithImage.tintColor,
                        @"The MDC button should have the same tint as the UIBarButtonItem");
  XCTAssertEqualObjects(
      [destinationButton imageForState:UIControlStateNormal], itemWithImage.image,
      @"The MDC button should have a normal state image equal to the UIBarButtonItem's image.");
  XCTAssertEqual(
      destinationButton.inkStyle, MDCInkStyleUnbounded,
      @"MDC buttons with only an image should use unbounded ink when used within a button bar.");
  XCTAssertEqual(destinationButton.tag, itemWithImage.tag,
                 @"The MDC button should have the same tag as the UIBarButtonItem.");
}

- (void)testConfigureButtonFromButtonItemWithTitleAndImage {
  // Given
  UIBarButtonItem *itemWithTitleAndImage =
      [[UIBarButtonItem alloc] initWithImage:[[UIImage alloc] init]
                                       style:UIBarButtonItemStylePlain
                                      target:nil
                                      action:nil];
  itemWithTitleAndImage.title = @"Title";
  itemWithTitleAndImage.tag = 0x13579bdf;
  itemWithTitleAndImage.tintColor = [UIColor colorWithRed:0.25 green:0.75 blue:0.625 alpha:0.5];
  MDCButton *destinationButton = [[MDCButton alloc] initWithFrame:CGRectZero];

  // When
  [MDCAppBarButtonBarBuilder configureButton:destinationButton
                              fromButtonItem:itemWithTitleAndImage];

  // Then
  NSString *expectedTitle = destinationButton.isUppercaseTitle
                                ? [itemWithTitleAndImage.title uppercaseString]
                                : itemWithTitleAndImage.title;
  XCTAssertEqualObjects(
      [destinationButton titleForState:UIControlStateNormal], expectedTitle,
      @"The MDC button should have a normal state title equal to the UIBarButtonItem's title.");
  XCTAssertEqualObjects(destinationButton.tintColor, itemWithTitleAndImage.tintColor,
                        @"The MDC button should have the same tint as the UIBarButtonItem");
  XCTAssertEqualObjects(
      [destinationButton imageForState:UIControlStateNormal], itemWithTitleAndImage.image,
      @"The MDC button should have a normal state image equal to the UIBarButtonItem's image.");
  XCTAssertEqual(destinationButton.inkStyle, MDCInkStyleBounded,
                 @"MDC buttons with a title should use bounded ink when used within a button bar.");
  XCTAssertEqual(destinationButton.tag, itemWithTitleAndImage.tag,
                 @"The MDC button should have the same tag as the UIBarButtonItem.");
}

@end

NS_ASSUME_NONNULL_END
